home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / Level 1 Extensions 20Jul94 / Numbers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  7.3 KB  |  278 lines  |  [TEXT/KAHL]

  1. /* Numbers.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Debug.h"
  21. #include "Audit.h"
  22. #include "Definitions.h"
  23.  
  24. #include "Numbers.h"
  25. #include "Memory.h"
  26.  
  27.  
  28. #define FLOATTOSTRINGBUFSIZE (128)
  29.  
  30.  
  31. long                        StringToInteger(char* String, long Length)
  32.     {
  33.         return (long)StringToLongDouble(String,Length);
  34.     }
  35.  
  36.  
  37. char*                        IntegerToString(long Integer)
  38.     {
  39.         char*                    Temp;
  40.  
  41.         Temp = LongDoubleToString(Integer,37,1e-37,1e37); /* these bounds should be enough */
  42.         if (Temp != NIL)
  43.             {
  44.                 SetTag(Temp,"IntegerToString");
  45.             }
  46.         return Temp;
  47.     }
  48.  
  49.  
  50. long double            StringToLongDouble(char* String, long Length)
  51.     {
  52.         long double        Accumulator;
  53.         MyBoolean            Negative;
  54.         MyBoolean            Decimal;
  55.         long double        DecimalScan;
  56.         long                    Exponent;
  57.         long                    Scan;
  58.  
  59.         Negative = False;
  60.         Decimal = False;
  61.         Scan = 0;
  62.         while (Scan < Length)
  63.             {
  64.                 switch (String[Scan])
  65.                     {
  66.                         case '+':
  67.                         case ' ':
  68.                             break;
  69.                         case '-':
  70.                             /* this might not be a good idea... what does the */
  71.                             /* average user think? */
  72.                             Negative = !Negative;
  73.                             break;
  74.                         default:
  75.                             goto ContinuePoint;
  76.                     }
  77.                 Scan += 1;
  78.             }
  79.      ContinuePoint:
  80.         Accumulator = 0;
  81.         while (Scan != Length)
  82.             {
  83.                 switch (String[Scan])
  84.                     {
  85.                         default:
  86.                             goto ExitPoint;
  87.                         case '.':
  88.                             DecimalScan = 0.1;
  89.                             Decimal = True;
  90.                             break;
  91.                         case '0': case '1': case '2': case '3': case '4':
  92.                         case '5': case '6': case '7': case '8': case '9':
  93.                             if (!Decimal)
  94.                                 {
  95.                                     Accumulator = (10 * Accumulator) + (String[Scan] - '0');
  96.                                 }
  97.                              else
  98.                                 {
  99.                                     Accumulator = Accumulator + (DecimalScan * (String[Scan] - '0'));
  100.                                     DecimalScan = DecimalScan / 10;
  101.                                 }
  102.                             break;
  103.                         case 'e': case 'E':
  104.                             Exponent = StringToInteger(&(String[Scan + 1]),Length - Scan - 1);
  105.                             while (Exponent < 0)
  106.                                 {
  107.                                     Exponent += 1;
  108.                                     Accumulator /= 10;
  109.                                 }
  110.                             while (Exponent > 0)
  111.                                 {
  112.                                     Exponent -= 1;
  113.                                     Accumulator *= 10;
  114.                                 }
  115.                             goto ExitPoint;
  116.                     }
  117.                 Scan += 1;
  118.             }
  119.      ExitPoint:
  120.         if (Negative)
  121.             {
  122.                 Accumulator = - Accumulator;
  123.             }
  124.         return Accumulator;
  125.     }
  126.  
  127.  
  128. char*                        LongDoubleToString(long double Value, int NumDigits,
  129.                                     long double LowBound, long double HighBound)
  130.     {
  131.         char                    Buffer[FLOATTOSTRINGBUFSIZE];
  132.         int                        Index;
  133.         MyBoolean            ScientificNotation;
  134.         MyBoolean            Negative;
  135.         long                    Exponent;
  136.         long double        Checker;
  137.         MyBoolean            DecimalEmitted;
  138.         char*                    Thang;
  139.  
  140.         /* initialize buffer pointer */
  141.         Index = 0;
  142.         if (NumDigits > FLOATTOSTRINGBUFSIZE - 16)
  143.             {
  144.                 NumDigits = FLOATTOSTRINGBUFSIZE - 16;
  145.             }
  146.  
  147.         /* handle negative values right now */
  148.         Negative = (Value < 0);
  149.         if (Negative)
  150.             {
  151.                 Value = - Value;
  152.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  153.                     "LongDoubleToString:  buffer overflow"));
  154.                 Buffer[Index++] = '-';
  155.             }
  156.  
  157.         /* if value is equal to zero, return zero right now */
  158.         if (Value == 0)
  159.             {
  160.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  161.                     "LongDoubleToString:  buffer overflow"));
  162.                 Buffer[Index++] = '0';
  163.                 goto AllDonePoint;
  164.             }
  165.  
  166.         /* determine if we need to use scientific notation by */
  167.         /* comparing against the bounds passed in */
  168.         ScientificNotation = ((Value < LowBound) || (Value >= HighBound));
  169.         if (ScientificNotation)
  170.             {
  171.                 /* if it is scientific notation, we want to normalize the number */
  172.                 /* and remember what exponent we should output */
  173.                 Exponent = 0;
  174.                 while (Value < 1)
  175.                     {
  176.                         Value = Value * 10;
  177.                         Exponent -= 1;
  178.                     }
  179.                 while (Value >= 10)
  180.                     {
  181.                         Value = Value / 10;
  182.                         Exponent += 1;
  183.                     }
  184.             }
  185.  
  186.         /* increment the checker thing until it is high enough */
  187.         Checker = 1;
  188.         while (Checker * 10 <= Value)
  189.             {
  190.                 Checker = Checker * 10;
  191.             }
  192.  
  193.         /* perform the actual scan */
  194.         DecimalEmitted = False;
  195.         while ((Checker >= 1) || ((NumDigits > 0) && (Value != 0)))
  196.             {
  197.                 int                    Count;
  198.  
  199.                 /* find out what digit to put */
  200.                 Count = 0;
  201.                 while (Value >= ((Count + 1) * Checker))
  202.                     {
  203.                         Count += 1;
  204.                     }
  205.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  206.                     "LongDoubleToString:  buffer overflow"));
  207.                 Buffer[Index++] = '0' + Count;
  208.                 Value -= Count * Checker;
  209.                 /* decrement digit count */
  210.                 NumDigits -= 1;
  211.                 /* put a decimal if appropriate */
  212.                 if (!DecimalEmitted && (Checker == 1) && (NumDigits > 0) && (Value != 0))
  213.                     {
  214.                         DecimalEmitted = True;
  215.                         ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  216.                             "LongDoubleToString:  buffer overflow"));
  217.                         Buffer[Index++] = '.';
  218.                     }
  219.                 /* decrement digit position */
  220.                 Checker /= 10;
  221.             }
  222.  
  223.         /* if it was scientific notation, then put the exponent on */
  224.         if (ScientificNotation)
  225.             {
  226.                 long                    IntChecker;
  227.  
  228.                 /* put the 'e' */
  229.                 ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  230.                     "LongDoubleToString:  buffer overflow"));
  231.                 Buffer[Index++] = 'e';
  232.                 /* check for negative exponent */
  233.                 if (Exponent < 0)
  234.                     {
  235.                         Exponent = - Exponent;
  236.                         ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  237.                             "LongDoubleToString:  buffer overflow"));
  238.                         Buffer[Index++] = '-';
  239.                     }
  240.                 /* initialize the integer thing */
  241.                 IntChecker = 1;
  242.                 while ((IntChecker * 10) <= Exponent)
  243.                     {
  244.                         /* we don't have to worry about integer overflow because even */
  245.                         /* a long double's exponent doesn't approach the integer's limit */
  246.                         IntChecker *= 10;
  247.                     }
  248.                 /* perform the integer conversion scan */
  249.                 while (IntChecker > 0)
  250.                     {
  251.                         int                    Count;
  252.  
  253.                         /* figure out the digit's value */
  254.                         Count = 0;
  255.                         while (Exponent >= ((Count + 1) * IntChecker))
  256.                             {
  257.                                 Count += 1;
  258.                             }
  259.                         /* emit the digit */
  260.                         ERROR(Index >= FLOATTOSTRINGBUFSIZE,PRERR(ForceAbort,
  261.                             "LongDoubleToString:  buffer overflow"));
  262.                         Buffer[Index++] = '0' + Count;
  263.                         /* update the values */
  264.                         Exponent -= Count * IntChecker;
  265.                         IntChecker /= 10;
  266.                     }
  267.             }
  268.  
  269.         /* finally, create the thang so we can output it */
  270.      AllDonePoint:
  271.         Thang = AllocPtrCanFail(Index,"LongDoubleToString");
  272.         if (Thang != NIL)
  273.             {
  274.                 CopyData(&(Buffer[0]),&(Thang[0]),Index);
  275.             }
  276.         return Thang;
  277.     }
  278.